/*
X2Play
Copyright (C) 2008  Jitu Das

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef XMMS2CONN_CPP
#define XMMS2CONN_CPP

#include "xmms2conn.h"

XMMS2Conn::XMMS2Conn(const std::string &name) : QThread(), Xmms::Client(name) {
	// connection code based on Konfetka
	char * path =  getenv("XMMS_PATH");
	try {
		if (path!=NULL)
		((Xmms::Client*)this)->connect(path);
		else
	        ((Xmms::Client*)this)->connect();
	}
	catch( Xmms::connection_error& err ) {
 		std::cout << "Connection failed: " << err.what() << std::endl;
		std::string str = err.what();
		if (std::string(err.what())=="xmms2d is not running.") {
			QString command = "xmms2-launcher";
			QStringList arguments;
			bool first=true;
			while(QProcess::execute(command,arguments)) {
				std::cout << command.toStdString();
				if(arguments.size()>0) std::cout<<arguments.at(0).toStdString();
				std::cout << std::endl;
				int ret = QMessageBox::critical	(NULL,
							"Problem Connecting",
							"Cannot Connect to Server\nTry again?",
							QMessageBox::Yes | QMessageBox::No,
							QMessageBox::No);
				if(ret==(QMessageBox::No)) {
					exit(EXIT_FAILURE);
					return;
				}
					
				if(ret==(QMessageBox::Yes)&&first) {
					first = false;
					
					ret = QMessageBox::critical	(NULL,
								"Are You Root",
								"Are You Root",
								QMessageBox::Yes | QMessageBox::No,
								QMessageBox::No);
						if(ret==QMessageBox::Yes)
						arguments<<"--yes-run-as-root";
				}
			}
			
			if (path!=NULL)
				((Xmms::Client*)this)->connect(path);
			else
				((Xmms::Client*)this)->connect();
		}
		else {
			std::cout<<"Autostarting the server failed, either this is your configuration, or an unkown error was recieved."<<std::endl;
			exit(EXIT_FAILURE);
		}
	}
	searchFinished = true;
}

void XMMS2Conn::searchText(const QString &text) {
	if (isRunning()) {
		forceQuit = true;
		wait();
	}
	searchString = text.trimmed();
	forceQuit = false;
	searchFinished = false;
	start();
}

bool resultComparator(QStringList a, QStringList b) {
	if (a[4].toFloat() > b[4].toFloat()) return true;
	return false;
}

void XMMS2Conn::run() {
	//std::cout << std::endl << searchString << std::endl;
	Xmms::Coll::Union total;
	
	std::list<std::string> props;
	std::list<std::string>::iterator props_itr;
	props.push_back("title");
	props.push_back("artist");
	props.push_back("album");
	
	QStringList keywords = searchString.split(QChar(' '), QString::SkipEmptyParts, Qt::CaseInsensitive);
	try {
		for (props_itr=props.begin(); props_itr!=props.end(); props_itr++) {
			for (int i=0; i<keywords.size(); i++) {
				if (forceQuit) return;
				Xmms::CollPtr c = collection.parse((*props_itr)+"~'"+keywords[i].toStdString()+"'");
				total.addOperand(*c);
			}
		}
	} catch (Xmms::collection_parsing_error c) {
		return;
	}
	
	props.push_back("id");
	
	if (forceQuit) return;
	Xmms::List <Xmms::Dict> list = collection.queryInfos(total,props);
	
	QList<QStringList> results;
	for (list.first();list.isValid(); ++list) {
		if (forceQuit) return;
		QStringList curEntry;
		float score = 0;
		int props_val = 3;
		for (props_itr=props.begin(); props_itr!=props.end(); props_itr++) {
			if (forceQuit) return;
			if(list->contains(*props_itr)) {
				if ((*props_itr).compare("id") == 0)
					curEntry << QString::number((list->get<int32_t>(*props_itr)));
				else {
					QString curProp = QString::fromStdString((list->get<std::string>(*props_itr)).c_str());
					curEntry << curProp;
					if (curProp.contains(searchString, Qt::CaseInsensitive)) score += searchString.size();
					else {
						for (int i=0; i<keywords.size(); i++) {
							if (forceQuit) return;
							if (curProp == keywords[i], Qt::CaseInsensitive) score += props_val * (keywords.size()-i)/(double)keywords.size()*keywords[i].size()/2.0 * 1.1;
							else if (curProp.startsWith(keywords[i], Qt::CaseInsensitive)) score += props_val * (keywords.size()-i)/(double)keywords.size()*keywords[i].size()/2.0;
							else if (curProp.contains(keywords[i], Qt::CaseInsensitive)) score += props_val * (keywords.size()-i)/(double)keywords.size()*keywords[i].size()/2.0 * 0.9;
						}
					}
				}
			}
			else curEntry << QString("");
			props_val--;
		}
		curEntry << QString::number(score);
		results << curEntry;
	}
	if (forceQuit) return;
	
	std::list<QStringList> stdResults = results.toStdList();
	stdResults.sort(resultComparator);
	if (stdResults.size() > 100) stdResults.resize(100);
	results = QList<QStringList>::fromStdList(stdResults);
	
	if (!searchString.compare(tr("next"))) {
		QStringList cmd;
		cmd << "next" << "command" << "" << "next" << "-1";
		results.insert(0, cmd);
	} else if (!searchString.compare(tr("prev"))) {
		QStringList cmd;
		cmd << "previous" << "command" << "" << "prev" << "-1";
		results.insert(0, cmd);
	} else if (!searchString.compare(tr("stop"))) {
		QStringList cmd;
		cmd << "stop" << "command" << "" << "stop" << "-1";
		results.insert(0, cmd);
	} else if (!searchString.compare(tr("play"))) {
		QStringList cmd;
		cmd << "play" << "command" << "" << "play" << "-1";
		results.insert(0, cmd);
	} else if (!searchString.compare(tr("pause"))) {
		QStringList cmd;
		cmd << "pause" << "command" << "" << "pause" << "-1";
		results.insert(0, cmd);
	} else if (!searchString.compare(tr("current"))) {
		unsigned int curId = playback.currentID();
		if (curId != 0) {
			QStringList cmd;
			Xmms::Dict curSong = Xmms::Dict(medialib.getInfo(curId));
			cmd << QString::fromStdString(curSong.contains("title")?curSong.get<std::string>("title"):"Unknown");
			cmd << QString::fromStdString(curSong.contains("artist")?curSong.get<std::string>("artist"):"Unknown");
			cmd << QString::fromStdString(curSong.contains("album")?curSong.get<std::string>("album"):"Unknown");
			cmd << QString::number(curSong.contains("id")?curSong.get<int32_t>("id"):-1);
			cmd << "-1";
			results.insert(0, cmd);
		}
	}
	
	searchFinished = true;
	emit updatedMatches(results);
}

void XMMS2Conn::doCommand(const QString &cmd) {
	if (cmd == "next") {
		playlist.setNextRel(1);
		playback.tickle();
	} else if (cmd == "prev") {
		playlist.setNextRel(-1);
		playback.tickle();
	} else if (cmd == "stop") {
		playback.stop();
	} else if (cmd == "play") {
		playback.start();
	} else if (cmd == "pause") {
		playback.pause();
	}
}

void XMMS2Conn::playId(unsigned int id, bool queue) {
	//std::cout << id << std::endl;
	if (id <= 0) return;
	unsigned int curpos = playlist.currentPos();
	playlist.insertId(curpos+1, id);
	playlist.setNext(curpos+1);
	if (!queue) {
		playback.tickle();
		playback.start();
	}
}

void XMMS2Conn::waitUntilReady() {
	while (!searchFinished);
}

#endif
